<template>
	<view class="wui-upload">
		<block v-if="fileList && fileList.length">
			<view class="file-wrap" hover-class="file-wrap-hover" @click="previewFile(index)" v-for="(file, index) in fileList" :key="index">
				<image class="preview-img" :src="file.blob || file.url"></image>
				<view class="delete-file" @click.stop="deleteFile(index)"><text class="iconfont icon-wui-close"></text></view>
				<view class="file-mask" v-if="!file.url && file.progress !== 100" :style="{ top: '-' + file.progress + '%' }"></view>
				<view class="file-progress" v-if="!file.url && file.progress !== 100 && !file.error">{{ file.progress }}%</view>
				<view class="file-error" v-if="file.error">上传失败</view>
			</view>
		</block>
		<view class="add-file file-wrap" hover-class="file-wrap-hover" @click="chooseFile"><text class="iconfont icon-wui-camera"></text></view>
	</view>
</template>

<script>
export default {
	name: 'w-upload',
	props: {
		// 上传地址
		action: {
			type: String,
			default: ''
		},
		// 要上传的file的name(跟后端保持一致)
		name: {
			type: String,
			default: 'file'
		},
		// v-moal绑定的值
		value: {
			type: Array,
			default: () => []
		},
		// 文件类型
		fileType: {
			type: String,
			default: 'all'
		},
		// 一次上传数量
		fileCount: {
			type: Number,
			default: 5
		},
		header: {
			type: Object,
			default() {
				return {};
			}
		},
		// 预览上传的图片时的裁剪模式，和image组件mode属性一致
		imageMode: {
			type: String,
			default: 'aspectFill'
		},
		// 所选的图片的尺寸
		sizeType: {
			type: Array,
			default: () => ['original', 'compressed']
		},
		// 选择图片的来源
		sourceType: {
			type: Array,
			default: () => ['album', 'camera']
		},
		// 删除前操作
		beforeDelete: {
			type: Function
		},
		// 上传前操作
		beforeUpload: {
			type: Function
		},
		// 上传失败后操作
		afterUploadError: {
			type: Function
		}
	},
	watch: {
		value(val) {
			this.fileList = val;
		},
		fileList(val) {
			this.$emit('input', val);
		}
	},
	data() {
		return {
			fileList: this.value
		};
	},
	methods: {
		// 删除文件
		deleteFile(index) {
			if (this.beforeDelete instanceof Function) {
				const beforeDeleteResult = this.beforeDelete(index);
				// 返回值必须是一个布尔值
				if (beforeDeleteResult) this.fileList.splice(index, 1);
			} else {
				this.fileList.splice(index, 1);
			}
		},
		// 预览图片
		previewFile(index) {
			// 预览列表
			let previewArr = [];
			// previewArr.push(file.blob||file.url)  为什么这样写？因为v-modal绑定的时候一般会绑定url而没有临时的blob地址，只有上传的时候才有blob地址
			this.fileList.forEach(file => previewArr.push(file.blob || file.url));
			uni.previewImage({
				current: index,
				urls: previewArr
			});
		},
		// 选择文件
		chooseFile() {
			
			
			console.log(this.value.length)
			let length = this.fileList.length 
			
			this.chooseFilePromise().then(res => {
				res.tempFiles.forEach(val => {
					// 这里可以做上传前的大小限制
					this.fileList.push({
						blob: val.path,
						url: '',
						progress: 0,
						error: false,
						file: val
					});
				});
				// 选择文件后先判断v-modal是否绑定的有数据如果有数据 那么 index就不是从0开始
				this.uploadFile(length);
			});
		},

		// 选择图片promise
		chooseFilePromise() {
			return new Promise((resolve, reject) => {
				// #ifdef H5
				uni.chooseFile({
					count: this.fileCount,
					type: this.fileType,
					success: resolve,
					fail: reject
				});
				// #endif
				// #ifdef MP-WEIXIN
				wx.chooseImage({
					count: this.fileCount,
					sizeType: this.sizeType,
					sourceType: this.sourceType,
					success: resolve,
					fail: reject
				});
				// #endif
			});
		},

		// 上传的核心代码
		uploadFile(index = 0) {
			if (index === this.fileList.length) {
				// 全部上传完成
				// 处理
				return false;
			}
			// 处理上传前操作
			if (this.beforeUpload instanceof Function) {
				const beforeDeleteResult = this.beforeUpload(index);
				// 返回值必须是一个布尔值 true 表示继续向下进行上传  false 直接进行下一个文件上传
				if (!beforeDeleteResult) {
					this.uploadError(index);
					return this.uploadFile(index + 1);
				}
			}

			// 创建上传对象
			const task = uni.uploadFile({
				url: this.action,
				name: this.name,
				filePath: this.fileList[index].blob,
				formData: this.formData,
				header: this.header,
				success: res => {
					if (![200, 201, 204].includes(res.statusCode)) {
						this.uploadError(index);
						return false;
					}
					// 调用上传成功 传输后端返回结果 和 当前上传的文件索引值
					this.$emit('uploadSuccess', index, JSON.parse(res.data));
					// 上传成功 继续上传下一个文件
					this.uploadFile(index + 1);
				},
				fail: e => {
					this.uploadError(index, e);
					// 上传失败 继续上传下一个文件
					this.uploadFile(index + 1);
				},
				complete: res => {}
			});
			// 上传进度监听
			task.onProgressUpdate(res => {
				if (res.progress > 0) {
					this.fileList[index].progress = res.progress;
				}
			});
		},
		// 上传失败
		uploadError(index, err) {
			if (this.afterUploadError instanceof Function) {
				const afterUploadErrorResult = this.afterUploadError(index, err);
				// 返回值必须是一个布尔值
				if (afterUploadErrorResult) this.fileList[index].error = true;
			} else {
				this.fileList[index].error = true;
			}
		}
	}
};
</script>

<style lang="scss" scoped>
.wui-upload {
	display: flex;
	flex-wrap: wrap;
	.file-wrap {
		width: 200rpx;
		height: 200rpx;
		margin: 10rpx;
		background-color: #f7f8fa;
		display: flex;
		justify-content: center;
		align-items: center;
		position: relative;
		overflow: hidden;
		.preview-img {
			width: 100%;
			height: 100%;
		}
		.delete-file {
			position: absolute;
			top: 0;
			right: 0;
			width: 36rpx;
			height: 36rpx;
			display: flex;
			justify-content: center;
			align-items: center;
			color: #fff;
			z-index: 4;
			background-color: #000;
			border-bottom-left-radius: 26rpx;
			.iconfont {
				font-size: 22rpx;
			}
		}
		.file-mask,
		.file-error,
		.file-progress {
			position: absolute;
			top: 0;
			left: 0;
			width: 100%;
			height: 100%;
			display: flex;
			justify-content: center;
			align-items: center;
			color: #fff;
		}
		.file-mask {
			z-index: 1;
			background-color: rgba(0, 0, 0, 0.4);
		}

		.file-progress {
			z-index: 2;
		}
		.file-error {
			z-index: 3;
			font-size: 24rpx;
		}
		.icon-wui-camera {
			color: #dcdee0;
			font-size: 64rpx;
		}
	}
	.file-wrap-hover {
		background-color: #f2f3f5;
	}
}
</style>
